package com.titaniume.sync;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @ProjectName: juc
 * @Package: com.titaniume.sync
 * @ClassName: SyncLockDemo
 * @Author: huangrenfei
 * @Description: 可重入锁
 * @Date: 2021/11/23 10:28
 * @Version: 1.0
 */
public class SyncLockDemo {


    public static void main(String[] args) {

        //new SyncLockDemo().add(); //Exception in thread "main" java.lang.StackOverflowError

        SyncLockDemo syncLockDemo = new SyncLockDemo();
//        syncLockDemo.syncBlock();
        //t1：外层
        // t1：中层
        // t1：内层
        syncLockDemo.LockMethod();

        //理解：synchronized 可重入锁，其实就是同一把锁 可以进入内外层
    }


    //Lock演示可重入锁
    public void LockMethod() {


        ReentrantLock reentrantLock = new ReentrantLock();


        new Thread(() -> {
            try {
                //上锁
                reentrantLock.lock();
                System.out.println(Thread.currentThread().getName() + "外层");
                try {
                    //上锁
                    reentrantLock.lock();
                    System.out.println(Thread.currentThread().getName() + "内层");
                } finally {
                    //解锁
                    reentrantLock.unlock();
                }
            } finally {
                //解锁
                reentrantLock.unlock();
            }

        }, "p1").start();


        new Thread(() -> {
            try {
                //上锁
                reentrantLock.lock();
                System.out.println("-----p2:"+Thread.currentThread().getName());
            } finally {
                //解锁
                reentrantLock.unlock();
            }

        }, "p2").start();


        //注意 使用Lock 上锁之后一定要解锁 不然在后面的线程后一直等待
    }


    //synchronized 同步方法 递归锁
    public void add() {
        add();
    }

    //synchronized 同步代码块
    public void syncBlock() {
        Object o = new Object();

        new Thread(() -> {
            synchronized (o) {
                System.out.println(Thread.currentThread().getName() + "：外层");
                synchronized (o) {
                    System.out.println(Thread.currentThread().getName() + "：中层");
                    synchronized (o) {
                        System.out.println(Thread.currentThread().getName() + "：内层");
                    }
                }
            }
        }, "t1").start();
    }

}
